package com.vdong.trade.trading.service.impl;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.fastjson.JSON;
import com.vdong.trade.order.facade.OrderFacade;
import com.vdong.trade.order.facade.enums.EventEnum;
import com.vdong.trade.trading.common.constants.WechatPayConstants;
import com.vdong.trade.trading.common.contract.AbstractResponse;
import com.vdong.trade.trading.common.enums.PayReturnCodeEnum;
import com.vdong.trade.trading.common.exception.ServiceException;
import com.vdong.trade.trading.common.exception.ValidateException;
import com.vdong.trade.trading.common.utils.HttpClientUtil;
import com.vdong.trade.trading.common.utils.WechatPayUtil;
import com.vdong.trade.trading.entity.dto.param.DisbOrderPayDoneParamDTO;
import com.vdong.trade.trading.entity.dto.param.PayDonePramDTO;
import com.vdong.trade.trading.entity.dto.param.PaymentNotifyRequestDTO;
import com.vdong.trade.trading.entity.dto.result.PaymentNotifyResponseDTO;
import com.vdong.trade.trading.entity.dto.param.PaymentRequestDTO;
import com.vdong.trade.trading.entity.mo.WechatPayDataExampleMo;
import com.vdong.trade.trading.entity.mo.WechatPayDataMo;
import com.vdong.trade.trading.entity.mo.WechatPayDataWithBLOBsMo;
import com.vdong.trade.trading.facade.enums.PayChannelEnum;
import com.vdong.trade.trading.facade.enums.WechatPayEnums;
import com.vdong.trade.trading.respository.WechatPayDataMapper;
import com.vdong.trade.trading.service.BasePayment;
import com.vdong.trade.trading.service.TransactionPayService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.lamb.framework.common.remote.FacadeResult;
import org.lamb.framework.common.util.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author <a href="mailto:clf@vdongzc.com">clf</a>
 * @Description: TransactionPayServiceImpl
 * @Date Create on 2018-12-13 15:10:22
 * @since version1.0
 */
@Service
@Slf4j
public class TransactionPayServiceImpl implements TransactionPayService {

    @Autowired
    private WechatPayDataMapper wechatPayDataMapper;

    @Reference
    private OrderFacade orderFacade;

    @Override
    public FacadeResult<AbstractResponse> execPay(PaymentRequestDTO paymentRequest) {
        log.info("支付接口execPay:[{}]", JSON.toJSONString(paymentRequest));
        AbstractResponse paymentResponse = null;
        try {
            if (paymentRequest == null) {
                throw new ValidateException("请求参数为空!");
            }
            if (StringUtil.hasBlank(paymentRequest.getPayChannel())) {
                throw new ValidateException("支付渠道 ==> payChannel不能为空!");
            }

            paymentResponse = BasePayment.paymentMap.
                    get(paymentRequest.getPayChannel()).process(paymentRequest);

            //支付失败
            if (!PayReturnCodeEnum.SUCCESS.getCode().equals(paymentResponse.getCode())) {
                return FacadeResult.buildFail(paymentResponse.getCode(), paymentResponse.getMsg());
            }

        } catch (ValidateException e) {
            log.error("支付接口execPay数据验证异常:", e);
            return FacadeResult.buildFail(e.getErrorMessage());
        } catch (ServiceException e) {
            log.error("支付接口execPay业务处理异常:", e);
            return FacadeResult.buildFail(e.getErrorMessage());
        } catch (Exception e) {
            log.error("支付接口execPay异常:", e);
            return FacadeResult.buildFail(PayReturnCodeEnum.SYSTEM_ERROR.getCode(), PayReturnCodeEnum.SYSTEM_ERROR.getMsg());
        } finally {
            log.info("execPay return result:[{}]", JSON.toJSONString(paymentResponse));
        }

        return FacadeResult.buildSucc(paymentResponse);
    }

    @Override
    public String paymentResultNotify(PaymentNotifyRequestDTO request) {
        try {
            PaymentNotifyResponseDTO dto = (PaymentNotifyResponseDTO) BasePayment.paymentMap.
                    get(request.getPayChannel()).completePayment(request.getResultStr());

            PayChannelEnum payChannelEnum = PayChannelEnum.getEnumByCode(request.getPayChannel());
            String desc = null;
            if (payChannelEnum != null) {
                desc = payChannelEnum.getDesc();
            }
            if (StringUtil.hasBlank(dto.getResult())) {
                log.error("{}支付异步回调number/nonceStr:[{}],业务处理:【ERROR】", desc, dto.getNumber());
                return null;
            } else {
                log.info("{}支付异步回调number/nonceStr:[{}],业务处理:【SUCCESS】", desc, dto.getNumber());
                return dto.getResult();
            }
        } catch (Exception e) {
            log.error("支付异步回调异常:", e);
            return null;
        }
    }

    @Override
    public FacadeResult queryOrder(String nonceStr, Boolean flag) {
        log.info("TransactionPayService.queryOrder接口入参nonceStr:[{}],flag:[{}]", nonceStr, flag);
        try {
            if (StringUtil.hasBlank(nonceStr)) {
                return FacadeResult.buildFail("入参不能为空!");
            }
            WechatPayDataExampleMo selectMo = new WechatPayDataExampleMo();
            selectMo.createCriteria().andNonceStrEqualTo(nonceStr);

            List<WechatPayDataMo> list = wechatPayDataMapper.selectByExample(selectMo);

            if (CollectionUtils.isEmpty(list)) {
                log.error("主动查询订单:获取支付订单数据异常! ==> nonceStr:[{}]", nonceStr);
                return FacadeResult.buildFail("主动查询订单:获取支付订单数据异常!");
            }

            WechatPayDataMo wechatPayDataMo = list.get(0);
            if (flag) {
                if (!WechatPayEnums.PayStatusEnum.PAY_AWAIT.getStatus().equals(wechatPayDataMo.getStatus())) {
                    return FacadeResult.buildFail("主动查询订单数据状态异常,不是预订单初始状态/已同步回调,待支付!");
                }
            }
            Map<String, String> result = BasePayment.paymentMap.
                    get(PayChannelEnum.WECHAT_PAY.getCode()).queryOrder(wechatPayDataMo.getOutTradeNo());

            if (!flag) {
                return FacadeResult.buildSucc(result);
            }
            if (WechatPayConstants.FAIL.equals(result.get(WechatPayConstants.RETURN_CODE))) {
                return FacadeResult.buildFail(result.get(WechatPayConstants.RETURN_MSG));
            }

            if (WechatPayConstants.FAIL.equals(result.get(WechatPayConstants.RESULT_CODE))) {
                return FacadeResult.buildFail(result.get(WechatPayConstants.ERR_CODE_DES));
            }

            WechatPayDataWithBLOBsMo updateWechatDataMo = new WechatPayDataWithBLOBsMo();
            updateWechatDataMo.setCallbackTime(new Date());
            updateWechatDataMo.setCallback(JSON.toJSONString(result));
            Boolean returnOrderCode = true;
            if (WechatPayConstants.SUCCESS.equals(result.get(WechatPayConstants.TRADE_STATE))) {
                // 更新订单数据状态为支付成功
                updateWechatDataMo.setStatus(WechatPayEnums.PayStatusEnum.PAY_SUCCESS.getStatus());
            } else {
                // 更新订单数据状态为支付失败
                updateWechatDataMo.setStatus(WechatPayEnums.PayStatusEnum.PAY_FAILED.getStatus());
                returnOrderCode = false;
            }

            WechatPayDataExampleMo updateWechatDataExampleMo = new WechatPayDataExampleMo();
            updateWechatDataExampleMo.createCriteria().andIdEqualTo(wechatPayDataMo.getId())
                    .andStatusEqualTo(WechatPayEnums.PayStatusEnum.PAY_AWAIT.getStatus());

            int count = wechatPayDataMapper.updateByExampleSelective(updateWechatDataMo, updateWechatDataExampleMo);
            if (count < 1) {
                log.error("主动查询订单成功:更新订单数据失败! ==> id:[{}],nonceStr:[{}]", list.get(0).getId(), nonceStr);
                return FacadeResult.buildFail("主动查询订单成功:更新订单数据失败!");
            }

            try {
                DisbOrderPayDoneParamDTO paramDTO = new DisbOrderPayDoneParamDTO();
                paramDTO.setEvent(EventEnum.DISB_PAYDONE.getValue());
                paramDTO.setData(PayDonePramDTO.builder().code(returnOrderCode)
                        .orderNo(wechatPayDataMo.getOrderNo())
                        .wechatDataId(wechatPayDataMo.getId().toString())
                        .kpayOrderNo(result.get(WechatPayConstants.ATTACH)).build());
                String execute = orderFacade.execute(JSON.toJSONString(paramDTO));
                log.info("微信订单主动查询成功,通知orderFacade.execute==> result:[{}]", JSON.toJSONString(execute));
            } catch (Exception e) {
                log.error("微信订单主动查询成功,通知订单服务异常:", e);
                return FacadeResult.buildFail("微信订单主动查询成功,通知订单服务异常!");
            }
            return FacadeResult.buildSucc();
        } catch (Exception e) {
            log.error("查询支付订单状态异常:", e);
            return FacadeResult.buildFail("查询异常!");
        }
    }

    public static void main(String[] args) throws Exception {

        HashMap<String, String> map = new HashMap<>();
        map.put(WechatPayConstants.RETURN_CODE, WechatPayConstants.SUCCESS);
        map.put(WechatPayConstants.RESULT_CODE, WechatPayConstants.SUCCESS);
        map.put(WechatPayConstants.NONCE_STR, "ie4U9Zva118yJfm7JdMWzfa5GuYVNEjo");
        String s = WechatPayUtil.mapToXml(map);
        //System.out.println(s);
        String s1 = HttpClientUtil.httpPost("http://promote-test.vdongzc.com/trading/pay/wechatPayNotifypay", null);
        System.err.println(s1);
    }
}
